package org.xp.judgeplatform.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import org.xp.judgeplatform.common.ApiResponse;
import org.xp.judgeplatform.common.PageResult;
import org.xp.judgeplatform.exception.BusinessException;
import org.xp.judgeplatform.pojo.dto.ProblemDTO.ProblemCreateDTO;
import org.xp.judgeplatform.pojo.dto.ProblemDTO.ProblemQueryDTO;
import org.xp.judgeplatform.pojo.dto.ProblemDTO.ProblemUpdateDTO;
import org.xp.judgeplatform.pojo.vo.ProblemVO.ProblemVO;
import org.xp.judgeplatform.service.ProblemService;


@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/problem")
@CrossOrigin(origins = {"http://localhost:5173"})
@Tag(name = "题目管理接口", description = "包含题目列表查询、创建、更新、删除、详情查询等操作")
public class ProblemController {

    private final ProblemService problemService;

    /**
     * 获取题目列表（仅管理员）
     * 普通用户应通过题目集访问题目
     */
    @GetMapping({"/list", "/admin"})
    @Operation(summary = "管理员查询题目列表", description = "分页查询题目列表，支持按标题、难度、分类筛选，仅管理员可访问")
    public ApiResponse<PageResult<ProblemVO>> getProblemList(ProblemQueryDTO problemQueryDTO) {
        if (problemQueryDTO.getPageNum() == null || problemQueryDTO.getPageNum() < 1) {
            problemQueryDTO.setPageNum(1);
        }
        if (problemQueryDTO.getPageSize() == null || problemQueryDTO.getPageSize() < 1) {
            problemQueryDTO.setPageSize(10);
        }
        
        log.info("管理员查询题目列表: {}", problemQueryDTO);
        PageResult<ProblemVO> result = problemService.getProblemsForAdmin(problemQueryDTO);
        return ApiResponse.success(result);
    }

    /**
     * 管理员创建题目
     */
    @PostMapping
    @PreAuthorize("hasAuthority('ADMIN')")
    @Operation(summary = "管理员创建题目", description = "创建新题目，包含标题、描述、样例等完整信息，仅管理员可访问")
    public ApiResponse<ProblemVO> createProblem(@Valid @RequestBody ProblemCreateDTO createDTO, Authentication authentication) {
        log.info("管理员创建题目: {}", createDTO.getTitle());
        Integer userId = getCurrentUserId(authentication);
        ProblemVO result = problemService.createProblem(createDTO, userId);
        return ApiResponse.success(result);
    }

    /**
     * 管理员更新题目
     */
    @PutMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN')")
    @Operation(summary = "管理员更新题目", description = "根据题目ID更新题目信息，仅管理员可访问")
    public ApiResponse<ProblemVO> updateProblem(@PathVariable Long id,
                                                @Valid @RequestBody ProblemUpdateDTO updateDTO) {
        log.info("管理员更新题目: id={}", id);

        ProblemVO result = problemService.updateProblem(id, updateDTO);

        return ApiResponse.success(result);
    }
    
    /**
     * 管理员删除题目
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN')")
    @Operation(summary = "管理员删除题目", description = "根据题目ID删除题目，仅管理员可访问")
    public ApiResponse<Void> deleteProblem(@PathVariable Long id) {
        log.info("管理员删除题目: id={}", id);
        
        problemService.deleteProblem(id);
        
        return ApiResponse.success();
    }
    
    /**
     * 获取题目详情
     */
    @GetMapping("/{id:\\d+}")
    @Operation(summary = "查询题目详情", description = "根据题目ID查询完整题目信息（所有用户可访问公开题目）")
    public ApiResponse<ProblemVO> getProblemById(@PathVariable Long id) {
        ProblemVO problemVO = problemService.getProblemById(id);
        return ApiResponse.success(problemVO);
    }

    /**
     * 获取当前登录用户ID
     */
    private Integer getCurrentUserId(Authentication authentication) {
        if (authentication == null || authentication.getPrincipal() == null) {
            throw new BusinessException(401, "未登录或登录已过期");
        }
        if (authentication.getPrincipal() instanceof org.xp.judgeplatform.security.UserPrincipal userPrincipal) {
            return userPrincipal.getId();
        }
        throw new BusinessException(401, "无法获取用户信息");
    }
}
